package distributed.controller;

import org.w3c.dom.NamedNodeMap;

import distributed.entity.Edge;
import distributed.entity.Event;
import distributed.entity.EventModel;
import distributed.entity.User;
import server.ClientState;
import server.Server;
import xml.Message;

/**
 * Controller to handle adding an edge to a given event
 * @author Sam Jaffe, Marcus Menghini
 *
 */
public class AddEdgeController implements IProtocolController{

	/** Processes a message from a client */
	public Message process(ClientState state, Message request) {
		String xmlString;
		// Grab the attributes of our edge request
		NamedNodeMap map = request.contents.getFirstChild().getAttributes();
		
		String id = map.getNamedItem("id").getNodeValue(); //Get the event id
		int height = Integer.decode(map.getNamedItem("height").getNodeValue()); // Get the height val
		int index = Integer.decode(map.getNamedItem("left").getNodeValue()); // Get the source line
		
		Event event = EventModel.getInstance().getEvent(id); //Get our event
		
		Edge add = new Edge(index, height); //Make the edge
		
		int next = event.addEdge(add); //Add it and check the new value
		
		xmlString = "<addEdgeResponse id='" + id + "' left='" + index 
			+ "' right='" + (index+1) + "' height='" + height + "'/></response>";
		
		if (next == -1){ //If it was -1, we got an invalid edge
			xmlString = Message.responseHeader(request.id(),
					"This edge is too close to another one") + xmlString;
			
			return new Message(xmlString); //So tell the client
		}
		else {
			xmlString = Message.responseHeader(request.id()) + xmlString;
		}
		
		// Add the edge to the DB
		DataBaseController dbc = DataBaseController.getInstance();
		dbc.insertEdge(add, id);
		
		Message send = new Message(xmlString);
		// Prep the message and send it off to everyone except the source
		for (User u : event.getUsers())
			if (u != null && !u.getID().equals(state.id()))
				if (Server.getState(u.getID()) != null)
					Server.getState(u.getID()).sendMessage(send);

		String turnXML = Message.responseHeader(request.id());
		//Lets get the next User's server id.
		String nextUser = event.getUsers()[next].getID();
		//If he doesn't exist
		while (Server.getState(nextUser) == null) {
			event.removeUser(next); //Deal with it
			if (next >= event.getNumUsers())
				next = 0;
			nextUser = event.getUsers()[next].getID();
		}
		
		Message turn;
		//If we're done send the response
		if (event.done()) {
			state.sendMessage(send);
			
			//Create the 'finished' turn response
			turnXML += "<turnResponse completed='true'/></response>";
			turn = new Message(turnXML);
			send = turn;
			//Send it to everyone
			for (User u : event.getUsers())
				if (u != null && !u.getID().equals(nextUser) && !u.getID().endsWith(state.id()))
					if (Server.getState(u.getID()) != null)
						Server.getState(u.getID()).sendMessage(send);
		}
		else {
			turnXML += "<turnResponse/></response>";
			turn = new Message(turnXML);
		}
		//Tell the next guy its his turn/we're done
		Server.getState(nextUser).sendMessage(turn);
		//Replay to the source client
		return send;
	}

	/**
	 * @return AddEdgeController
	 */
	public IProtocolController newCopy() {
		return new AddEdgeController();
	}

}
